package com.douqu.game.main.server;

import com.bean.core.buffer.ByteBuffer;
import com.douqu.game.core.database.model.ServerModel;
import com.douqu.game.core.e.E_PlayerStatus;
import com.douqu.game.core.entity.ArenaRank;
import com.douqu.game.core.entity.WorldInfo;
import com.douqu.game.core.entity.ext.BattleInfo;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.netty.NettyConnection;
import com.douqu.game.main.job.MatchJob;
import com.douqu.game.main.service.WorldService;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created by bean on 2017/7/27.
 */
public class WorldManager {

//    private static final long serialVersionUID = 1L;

    /**
     * 所有连接(包含未登录的)
     */
    private Map<Integer,NettyConnection> connectionMap = new ConcurrentHashMap<Integer,NettyConnection>();

    /**
     * 在线用户列表
     */
    private List<PlayerController> playerList = new CopyOnWriteArrayList<>();

    private Map<String,PlayerController> playerMap = new ConcurrentHashMap<>();

    /**
     * 匹配池
     */
    private List<MatchJob> matchPool = new CopyOnWriteArrayList<>();
    /***/
    private Map<String, MatchJob> matchJobMap = new ConcurrentHashMap<>();
    /**
     * key: 段位
     * value：此段位所有正在匹配的玩家
     */
    private Map<Integer, List<MatchJob>> gradeMatchPool = new ConcurrentHashMap<>();

    /**
     * 竞技场排行榜对象
     */
    private List<ArenaRank> arenaRankList = new CopyOnWriteArrayList<>();

    private WorldInfo worldInfo = new WorldInfo();

    public void load()
    {
        //从数据库加载流水号，防止重复，加载的时候加100000
        WorldService worldService = SpringContext.getBean(WorldService.class);

        ServerModel serverModel = worldService.find();

        worldInfo.load(serverModel);

        byte[] arenaRankData = serverModel.getArenaRank();
        if(arenaRankData != null)
        {
            ByteBuffer buffer = new ByteBuffer(arenaRankData);
            int size = buffer.readInt();
            ArenaRank arenaRank = null;
            for(int i = 0; i < size; i++)
            {
                arenaRank = new ArenaRank();
                arenaRank.loadFrom(buffer);
                arenaRankList.add(arenaRank);
            }
        }
    }


    public byte[] save()
    {
        ByteBuffer buffer = new ByteBuffer();
        int size = arenaRankList.size();
        buffer.writeInt(size);
        for(int i = 0; i < size; i++)
        {
            arenaRankList.get(i).writeTo(buffer);
        }
        return buffer.getBytes();
    }



    public void updateMatch()
    {
        for(MatchJob job : matchPool)
        {
            if(job.isLock())
                continue;

            if(job.isSuccess())
                removeMatch(job.getPlayer());
            else
                job.update();
        }
    }

    public synchronized void addMatch(PlayerController playerController)
    {
        playerController.setStatus(E_PlayerStatus.MATCHING);

        BattleInfo battleInfo = (BattleInfo) playerController.getPlayer().getExtInfo(BattleInfo.class);

        MatchJob job = new MatchJob(playerController, battleInfo.getLastTarget(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_PVP_ARENA.getNumber()));

        int grade = playerController.getPlayer().grade;
        List<MatchJob> gradePool = gradeMatchPool.get(grade);
        if(gradePool == null)
        {
            gradePool = new CopyOnWriteArrayList<>();
            gradeMatchPool.put(grade, gradePool);
        }

        gradePool.add(job);
        matchPool.add(job);
        matchJobMap.put(playerController.getObjectIndex(), job);
    }


    public synchronized void removeMatch(PlayerController playerController)
    {
        playerController.setStatus(E_PlayerStatus.FREE);

        MatchJob job = matchJobMap.get(playerController.getObjectIndex());
        if(job != null)
        {
            matchPool.remove(job);
            List<MatchJob> list = gradeMatchPool.get(playerController.getPlayer().grade);
            if(list != null)
                list.remove(job);
        }

        System.out.println("WorldManager removeMatch 从匹配池删除玩家：" + playerController);
    }

    public List<MatchJob> getMatchPoolByGrade(int grade)
    {
        return gradeMatchPool.get(grade);
    }

    public List<MatchJob> getMatchPool()
    {
        return matchPool;
    }




    /**
     * 玩家进入游戏世界
     * @param playerController
     */
    public synchronized void playerEnterGame(PlayerController playerController){
        if(getPlayerController(playerController.getObjectIndex()) == null)
        {
            playerList.add(playerController);

            playerMap.put(playerController.getObjectIndex(), playerController);

        }
    }


    public synchronized void playerExitGame(PlayerController playerController)
    {
        playerController.destroy();

        playerList.remove(playerController);
        playerMap.remove(playerController.getObjectIndex());
    }


    public PlayerController getPlayerController(String playerIndex){
        return playerMap.get(playerIndex);
    }

    public WorldInfo getWorldInfo() {
        return worldInfo;
    }

    public void setWorldInfo(WorldInfo worldInfo) {
        this.worldInfo = worldInfo;
    }

    public List<PlayerController> getPlayerList() {
        return playerList;
    }

    public List<ArenaRank> getArenaRankList() {
//        GameServer.getInstance().getWorldManager()
        return arenaRankList;
    }

    /**
     * 添加一个排名
     * @param objectIndex
     * @return
     */
    public ArenaRank addArenaRankInfo(String objectIndex){
        ArenaRank rankInfo= new ArenaRank();
        rankInfo.setRank(arenaRankList.size() + 1);
        rankInfo.setObjectIndex(objectIndex);
        return rankInfo;
    }


    /**
     * 根据排名获取排行榜信息
     * @param rank
     * @return
     */
    public ArenaRank getArenaRankInfo(int rank){
        ArenaRank rankInfo = rank < arenaRankList.size() - 1 ? arenaRankList.get(rank - 1) : null ;
        return rankInfo;
    }

    /**
     * 根据指定排名下的所有玩家
     * @return
     */
    public List<ArenaRank> getUnderTargetRankList(int maxRank){
        return arenaRankList.subList(0, maxRank);
    }



    /**
     * 根据两个排行榜名次，交换排行榜信息
     * @param rank1
     * @param rank2
     * @return
     */
    public boolean swapArenaRank(int rank1, int rank2){
        ArenaRank rankInfo1 = rank1 < arenaRankList.size() - 1 ? arenaRankList.get(rank1 - 1) : null ;
        ArenaRank rankInfo2 = rank1 < arenaRankList.size() - 1 ? arenaRankList.get(rank2 - 1) : null ;
        if(rankInfo1 != null || rankInfo2 != null){
            rankInfo1.setRank(rank2 - 1);
            rankInfo2.setRank(rank1 - 1);
            Collections.swap(arenaRankList, rank1 - 1, rank2 - 1);
        }else {
            return false;
        }
        return true;
    }



}
